// Decompiled on 周六 2月 22 19:31:49 CST 2025 with Zomboid Decompiler v0.1.3 using Vineflower.
package zombie;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.GregorianCalendar;
import java.util.concurrent.TimeUnit;
import se.krka.kahlua.vm.KahluaTable;
import zombie.Lua.LuaEventManager;
import zombie.Lua.LuaManager;
import zombie.ai.sadisticAIDirector.SleepingEvent;
import zombie.characters.IsoPlayer;
import zombie.characters.IsoZombie;
import zombie.core.Core;
import zombie.core.PerformanceSettings;
import zombie.core.Rand;
import zombie.core.Translator;
import zombie.core.logger.ExceptionLogger;
import zombie.core.math.PZMath;
import zombie.core.network.ByteBufferWriter;
import zombie.core.raknet.UdpConnection;
import zombie.debug.DebugLog;
import zombie.debug.DebugOptions;
import zombie.erosion.ErosionMain;
import zombie.iso.IsoWorld;
import zombie.iso.SliceY;
import zombie.iso.weather.ClimateManager;
import zombie.network.GameClient;
import zombie.network.GameServer;
import zombie.network.PacketTypes;
import zombie.network.ServerOptions;
import zombie.radio.ZomboidRadio;
import zombie.ui.SpeedControls;
import zombie.ui.UIManager;
import zombie.util.PZCalendar;

public final class GameTime {
    public static zombie.GameTime instance = new zombie.GameTime();
    public static final float MULTIPLIER = 0.8F;
    private static long serverTimeShift = 0L;
    private static boolean serverTimeShiftIsSet = false;
    private static boolean isUTest = false;
    public float TimeOfDay = 9.0F;
    public int NightsSurvived = 0;
    public PZCalendar Calender;
    public float FPSMultiplier = 1.0F;
    public float Moon = 0.0F;
    public float ServerTimeOfDay;
    public float ServerLastTimeOfDay;
    public int ServerNewDays;
    public float lightSourceUpdate = 0.0F;
    public float multiplierBias = 1.0F;
    public float LastLastTimeOfDay = 0.0F;
    private int HelicopterTime1Start = 0;
    public float PerObjectMultiplier = 1.0F;
    private int HelicopterTime1End = 0;
    private int HelicopterDay1 = 0;
    private float Ambient = 0.9F;
    private float AmbientMax = 1.0F;
    private float AmbientMin = 0.24F;
    private int Day = 22;
    private int StartDay = 22;
    private float MaxZombieCountStart = 750.0F;
    private float MinZombieCountStart = 750.0F;
    private float MaxZombieCount = 750.0F;
    private float MinZombieCount = 750.0F;
    private int Month = 7;
    private int StartMonth = 7;
    private float StartTimeOfDay = 9.0F;
    private float ViewDistMax = 42.0F;
    private float ViewDistMin = 19.0F;
    private int Year = 2012;
    private int StartYear = 2012;
    private double HoursSurvived = 0.0;
    private float MinutesPerDayStart = 30.0F;
    private float MinutesPerDay = this.MinutesPerDayStart;
    private float LastTimeOfDay;
    private int TargetZombies = (int)this.MinZombieCountStart;
    private boolean RainingToday = true;
    private boolean bGunFireEventToday = false;
    private float[] GunFireTimes = new float[5];
    private int NumGunFireEvents = 1;
    private long lastPing = 0L;
    private long lastClockSync = 0L;
    private KahluaTable table = null;
    private int minutesMod = -1;
    private boolean thunderDay = true;
    private boolean randomAmbientToday = true;
    private float Multiplier = 1.0F;
    private int dusk = 3;
    private int dawn = 12;
    private float NightMin = 0.0F;
    private float NightMax = 1.0F;
    private long minutesStamp = 0L;
    private long previousMinuteStamp = 0L;

    public GameTime() {
        serverTimeShift = 0L;
        serverTimeShiftIsSet = false;
    }

    public static zombie.GameTime getInstance() {
        return instance;
    }

    public static void setInstance(zombie.GameTime aInstance) {
        instance = aInstance;
    }

    public static void syncServerTime(long timeClientSend, long timeServer, long timeClientReceive) {
        long long0 = timeClientReceive - timeClientSend;
        long long1 = timeServer - timeClientReceive + long0 / 2L;
        long long2 = serverTimeShift;
        if (!serverTimeShiftIsSet) {
            serverTimeShift = long1;
        } else {
            serverTimeShift = serverTimeShift + (long1 - serverTimeShift) / 100L;
        }

        long long3 = 10000000L;
        if (Math.abs(serverTimeShift - long2) > long3) {
            sendTimeSync();
        } else {
            serverTimeShiftIsSet = true;
        }
    }

    public static long getServerTime() {
        if (isUTest) {
            return System.nanoTime() + serverTimeShift;
        } else if (GameServer.bServer) {
            return System.nanoTime();
        } else if (GameClient.bClient) {
            return !serverTimeShiftIsSet ? 0L : System.nanoTime() + serverTimeShift;
        } else {
            return 0L;
        }
    }

    public static long getServerTimeMills() {
        return TimeUnit.NANOSECONDS.toMillis(getServerTime());
    }

    public static boolean getServerTimeShiftIsSet() {
        return serverTimeShiftIsSet;
    }

    public static void setServerTimeShift(long tshift) {
        isUTest = true;
        serverTimeShift = tshift;
        serverTimeShiftIsSet = true;
    }

    private static void sendTimeSync() {
        ByteBufferWriter byteBufferWriter = GameClient.connection.startPacket();
        PacketTypes.PacketType.TimeSync.doPacket(byteBufferWriter);
        byteBufferWriter.putLong(System.nanoTime());
        byteBufferWriter.putFloat(instance.Multiplier);
        PacketTypes.PacketType.TimeSync.send(GameClient.connection);
    }

    public static void receiveTimeSync(ByteBuffer bb, UdpConnection connection) {
        if (GameServer.bServer) {
            long long0 = bb.getLong();
            long long1 = System.nanoTime();
            float _float = bb.getFloat();
            if (GameServer.bServer && !GameServer.bFastForward) {
                if (instance.Multiplier != _float) {
                    connection.validator.failTimeMultiplier(_float);
                } else {
                    connection.validator.successTimeMultiplier();
                }
            }

            ByteBufferWriter byteBufferWriter = connection.startPacket();
            PacketTypes.PacketType.TimeSync.doPacket(byteBufferWriter);
            byteBufferWriter.putLong(long0);
            byteBufferWriter.putLong(long1);
            PacketTypes.PacketType.TimeSync.send(connection);
        }

        if (GameClient.bClient) {
            long long2 = bb.getLong();
            long long3 = bb.getLong();
            long long4 = System.nanoTime();
            syncServerTime(long2, long3, long4);
            DebugLog.printServerTime = true;
        }
    }

    public float getRealworldSecondsSinceLastUpdate() {
        return 0.016666668F * this.FPSMultiplier;
    }

    public float getMultipliedSecondsSinceLastUpdate() {
        return 0.016666668F * this.getUnmoddedMultiplier();
    }

    public float getGameWorldSecondsSinceLastUpdate() {
        float _float = 1440.0F / this.getMinutesPerDay();
        return this.getTimeDelta() * _float;
    }

    public int daysInMonth(int year, int month) {
        if (this.Calender == null) {
            this.updateCalendar(this.getYear(), this.getMonth(), this.getDay(), (int)this.getTimeOfDay(), this.getMinutes());
        }

        int[] _int = new int[]{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
        _int[1] += this.getCalender().isLeapYear(year) ? 1 : 0;
        return _int[month];
    }

    public String getDeathString(IsoPlayer playerObj) {
        return Translator.getText("IGUI_Gametime_SurvivedFor", this.getTimeSurvived(playerObj));
    }

    public int getDaysSurvived() {
        float _float = 0.0F;

        for (int int0 = 0; int0 < IsoPlayer.numPlayers; int0++) {
            IsoPlayer isoPlayer = IsoPlayer.players[int0];
            if (isoPlayer != null) {
                _float = Math.max(_float, (float)isoPlayer.getHoursSurvived());
            }
        }

        int int1 = (int)_float / 24;
        return int1 % 30;
    }

    public String getTimeSurvived(IsoPlayer playerObj) {
        Object object = "";
        float _float = (float)playerObj.getHoursSurvived();
        Integer integer0 = (int)_float % 24;
        Integer integer1 = (int)_float / 24;
        Integer integer2 = integer1 / 30;
        integer1 = integer1 % 30;
        Integer integer3 = integer2 / 12;
        integer2 = integer2 % 12;
        String string0 = Translator.getText("IGUI_Gametime_day");
        String string1 = Translator.getText("IGUI_Gametime_year");
        String string2 = Translator.getText("IGUI_Gametime_hour");
        String string3 = Translator.getText("IGUI_Gametime_month");
        if (integer3 != 0) {
            if (integer3 > 1) {
                string1 = Translator.getText("IGUI_Gametime_years");
            }

            object = object + integer3 + " " + string1;
        }

        if (integer2 != 0) {
            if (integer2 > 1) {
                string3 = Translator.getText("IGUI_Gametime_months");
            }

            if (object.length() > 0) {
                object = object + ", ";
            }

            object = object + integer2 + " " + string3;
        }

        if (integer1 != 0) {
            if (integer1 > 1) {
                string0 = Translator.getText("IGUI_Gametime_days");
            }

            if (object.length() > 0) {
                object = object + ", ";
            }

            object = object + integer1 + " " + string0;
        }

        if (integer0 != 0) {
            if (integer0 > 1) {
                string2 = Translator.getText("IGUI_Gametime_hours");
            }

            if (object.length() > 0) {
                object = object + ", ";
            }

            object = object + integer0 + " " + string2;
        }

        if (object.trim().length() == 0) {
            int int0 = (int)(_float * 60.0F);
            int int1 = (int)(_float * 60.0F * 60.0F) - int0 * 60;
            object = int0 + " " + Translator.getText("IGUI_Gametime_minutes") + ", " + int1 + " " + Translator.getText("IGUI_Gametime_secondes");
        }

        return (String)object;
    }

    public String getZombieKilledText(IsoPlayer playerObj) {
        int _int = playerObj.getZombieKills();
        if (_int == 0 || _int > 1) {
            return Translator.getText("IGUI_Gametime_zombiesCount", _int);
        } else {
            return _int == 1 ? Translator.getText("IGUI_Gametime_zombieCount", _int) : null;
        }
    }

    public String getGameModeText() {
        String string0 = Translator.getTextOrNull("IGUI_Gametime_" + Core.GameMode);
        if (string0 == null) {
            string0 = Core.GameMode;
        }

        String string1 = Translator.getTextOrNull("IGUI_Gametime_GameMode", string0);
        if (string1 == null) {
            string1 = "Game mode: " + string0;
        }

        if (Core.bDebug) {
            string1 = string1 + " (DEBUG)";
        }

        return string1;
    }

    public void init() {
        this.setDay(this.getStartDay());
        this.setTimeOfDay(this.getStartTimeOfDay());
        this.setMonth(this.getStartMonth());
        this.setYear(this.getStartYear());
        if (zombie.SandboxOptions.instance.Helicopter.getValue() != 1) {
            this.HelicopterDay1 = Rand.Next(6, 10);
            this.HelicopterTime1Start = Rand.Next(9, 19);
            this.HelicopterTime1End = this.HelicopterTime1Start + Rand.Next(4) + 1;
        }

        this.setMinutesStamp();
    }

    public float Lerp(float start, float end, float delta) {
        if (delta < 0.0F) {
            delta = 0.0F;
        }

        if (delta >= 1.0F) {
            delta = 1.0F;
        }

        float float0 = end - start;
        float float1 = float0 * delta;
        return start + float1;
    }

    public void RemoveZombiesIndiscriminate(int i) {
        if (i != 0) {
            for (int _int = 0; _int < IsoWorld.instance.CurrentCell.getZombieList().size(); _int++) {
                IsoZombie isoZombie = (IsoZombie)IsoWorld.instance.CurrentCell.getZombieList().get(0);
                IsoWorld.instance.CurrentCell.getZombieList().remove(_int);
                IsoWorld.instance.CurrentCell.getRemoveList().add(isoZombie);
                isoZombie.getCurrentSquare().getMovingObjects().remove(isoZombie);
                _int--;
                if (--i == 0 || IsoWorld.instance.CurrentCell.getZombieList().isEmpty()) {
                    return;
                }
            }
        }
    }

    public float TimeLerp(float startVal, float endVal, float startTime, float endTime) {
        float float0 = getInstance().getTimeOfDay();
        if (endTime < startTime) {
            endTime += 24.0F;
        }

        boolean _boolean = false;
        if (float0 > endTime && float0 > startTime || float0 < endTime && float0 < startTime) {
            startTime += 24.0F;
            _boolean = true;
            startTime = endTime;
            endTime = startTime;
            if (float0 < startTime) {
                float0 += 24.0F;
            }
        }

        float float1 = endTime - startTime;
        float float2 = float0 - startTime;
        float float3 = 0.0F;
        if (float2 > float1) {
            float3 = 1.0F;
        }

        if (float2 < float1 && float2 > 0.0F) {
            float3 = float2 / float1;
        }

        if (_boolean) {
            float3 = 1.0F - float3;
        }

        float float4 = 0.0F;
        float3 = (float3 - 0.5F) * 2.0F;
        if ((double)float3 < 0.0) {
            float4 = -1.0F;
        } else {
            float4 = 1.0F;
        }

        float3 = Math.abs(float3);
        float3 = 1.0F - float3;
        float3 = (float)Math.pow((double)float3, 8.0);
        float3 = 1.0F - float3;
        float3 *= float4;
        float3 = float3 * 0.5F + 0.5F;
        return this.Lerp(startVal, endVal, float3);
    }

    public float getDeltaMinutesPerDay() {
        return this.MinutesPerDayStart / this.MinutesPerDay;
    }

    public float getNightMin() {
        return 1.0F - this.NightMin;
    }

    public void setNightMin(float min) {
        this.NightMin = 1.0F - min;
    }

    public float getNightMax() {
        return 1.0F - this.NightMax;
    }

    public void setNightMax(float max) {
        this.NightMax = 1.0F - max;
    }

    public int getMinutes() {
        return (int)((this.getTimeOfDay() - (float)((int)this.getTimeOfDay())) * 60.0F);
    }

    public void setMoon(float moon) {
        this.Moon = moon;
    }

    public void update(boolean bSleeping) {
        long _long = System.currentTimeMillis();
        if (GameClient.bClient && (this.lastPing == 0L || _long - this.lastPing > 10000L)) {
            sendTimeSync();
            this.lastPing = _long;
        }

        short _short = 9000;
        if (zombie.SandboxOptions.instance.MetaEvent.getValue() == 1) {
            _short = -1;
        }

        if (zombie.SandboxOptions.instance.MetaEvent.getValue() == 3) {
            _short = 6000;
        }

        if (!GameClient.bClient && this.randomAmbientToday && _short != -1 && Rand.Next(Rand.AdjustForFramerate(_short)) == 0 && !isGamePaused()) {
            zombie.AmbientStreamManager.instance.addRandomAmbient();
            this.randomAmbientToday = zombie.SandboxOptions.instance.MetaEvent.getValue() == 3 && Rand.Next(3) == 0;
        }

        if (GameServer.bServer && UIManager.getSpeedControls() != null) {
            UIManager.getSpeedControls().SetCurrentGameSpeed(1);
        }

        if (GameServer.bServer || !GameClient.bClient) {
            if (this.bGunFireEventToday) {
                for (int int0 = 0; int0 < this.NumGunFireEvents; int0++) {
                    if (this.TimeOfDay > this.GunFireTimes[int0] && this.LastLastTimeOfDay < this.GunFireTimes[int0]) {
                        zombie.AmbientStreamManager.instance.doGunEvent();
                    }
                }
            }

            if (this.NightsSurvived == this.HelicopterDay1
                && this.TimeOfDay > (float)this.HelicopterTime1Start
                && this.TimeOfDay < (float)this.HelicopterTime1End
                && !IsoWorld.instance.helicopter.isActive()
                && Rand.Next((int)(800.0F * this.getInvMultiplier())) == 0) {
                this.HelicopterTime1Start = (int)((float)this.HelicopterTime1Start + 0.5F);
                IsoWorld.instance.helicopter.pickRandomTarget();
            }

            if (this.NightsSurvived > this.HelicopterDay1
                && (zombie.SandboxOptions.instance.Helicopter.getValue() == 3 || zombie.SandboxOptions.instance.Helicopter.getValue() == 4)) {
                if (zombie.SandboxOptions.instance.Helicopter.getValue() == 3) {
                    this.HelicopterDay1 = this.NightsSurvived + Rand.Next(10, 16);
                }

                if (zombie.SandboxOptions.instance.Helicopter.getValue() == 4) {
                    this.HelicopterDay1 = this.NightsSurvived + Rand.Next(6, 10);
                }

                this.HelicopterTime1Start = Rand.Next(9, 19);
                this.HelicopterTime1End = this.HelicopterTime1Start + Rand.Next(4) + 1;
            }
        }

        int int1 = this.getHour();
        this.updateCalendar(
            this.getYear(), this.getMonth(), this.getDay(), (int)this.getTimeOfDay(), (int)((this.getTimeOfDay() - (float)((int)this.getTimeOfDay())) * 60.0F)
        );
        float float0 = this.getTimeOfDay();
        if (!isGamePaused()) {
            float float1 = 1.0F / this.getMinutesPerDay() / 60.0F * this.getMultiplier() / 2.0F;
            if (Core.bLastStand) {
                float1 = 1.0F / this.getMinutesPerDay() / 60.0F * this.getUnmoddedMultiplier() / 2.0F;
            }

            this.setTimeOfDay(this.getTimeOfDay() + float1);
            if (this.getHour() != int1) {
                LuaEventManager.triggerEvent("EveryHours");
            }

            if (!GameServer.bServer) {
                for (int int2 = 0; int2 < IsoPlayer.numPlayers; int2++) {
                    IsoPlayer isoPlayer0 = IsoPlayer.players[int2];
                    if (isoPlayer0 != null && isoPlayer0.isAlive()) {
                        isoPlayer0.setHoursSurvived(isoPlayer0.getHoursSurvived() + (double)float1);
                    }
                }
            }

            if (GameServer.bServer) {
                ArrayList arrayList0 = GameClient.instance.getPlayers();

                for (int int3 = 0; int3 < arrayList0.size(); int3++) {
                    IsoPlayer isoPlayer1 = (IsoPlayer)arrayList0.get(int3);
                    isoPlayer1.setHoursSurvived(isoPlayer1.getHoursSurvived() + (double)float1);
                }
            }

            if (GameClient.bClient) {
                ArrayList arrayList1 = GameClient.instance.getPlayers();

                for (int int4 = 0; int4 < arrayList1.size(); int4++) {
                    IsoPlayer isoPlayer2 = (IsoPlayer)arrayList1.get(int4);
                    if (isoPlayer2 != null && !isoPlayer2.isDead() && !isoPlayer2.isLocalPlayer()) {
                        isoPlayer2.setHoursSurvived(isoPlayer2.getHoursSurvived() + (double)float1);
                    }
                }
            }

            for (int int5 = 0; int5 < IsoPlayer.numPlayers; int5++) {
                IsoPlayer isoPlayer3 = IsoPlayer.players[int5];
                if (isoPlayer3 != null) {
                    if (isoPlayer3.isAsleep()) {
                        isoPlayer3.setAsleepTime(isoPlayer3.getAsleepTime() + float1);
                        SleepingEvent.instance.update(isoPlayer3);
                    } else {
                        isoPlayer3.setAsleepTime(0.0F);
                    }
                }
            }
        }

        if (!GameClient.bClient && float0 <= 7.0F && this.getTimeOfDay() > 7.0F) {
            this.setNightsSurvived(this.getNightsSurvived() + 1);
            this.doMetaEvents();
        }

        if (GameClient.bClient) {
            if (this.getTimeOfDay() >= 24.0F) {
                this.setTimeOfDay(this.getTimeOfDay() - 24.0F);
            }

            while (this.ServerNewDays > 0) {
                this.ServerNewDays--;
                this.setDay(this.getDay() + 1);
                if (this.getDay() >= this.daysInMonth(this.getYear(), this.getMonth())) {
                    this.setDay(0);
                    this.setMonth(this.getMonth() + 1);
                    if (this.getMonth() >= 12) {
                        this.setMonth(0);
                        this.setYear(this.getYear() + 1);
                    }
                }

                this.updateCalendar(this.getYear(), this.getMonth(), this.getDay(), (int)this.getTimeOfDay(), this.getMinutes());
                LuaEventManager.triggerEvent("EveryDays");
            }
        } else if (this.getTimeOfDay() >= 24.0F) {
            this.setTimeOfDay(this.getTimeOfDay() - 24.0F);
            this.setDay(this.getDay() + 1);
            if (this.getDay() >= this.daysInMonth(this.getYear(), this.getMonth())) {
                this.setDay(0);
                this.setMonth(this.getMonth() + 1);
                if (this.getMonth() >= 12) {
                    this.setMonth(0);
                    this.setYear(this.getYear() + 1);
                }
            }

            this.updateCalendar(this.getYear(), this.getMonth(), this.getDay(), (int)this.getTimeOfDay(), this.getMinutes());
            LuaEventManager.triggerEvent("EveryDays");
            if (GameServer.bServer) {
                GameServer.syncClock();
                this.lastClockSync = _long;
            }
        }

        float float2 = this.Moon * 20.0F;
        if (!ClimateManager.getInstance().getThunderStorm().isModifyingNight()) {
            this.setAmbient(this.TimeLerp(this.getAmbientMin(), this.getAmbientMax(), (float)this.getDusk(), (float)this.getDawn()));
        }

        if (Core.getInstance().RenderShader != null && Core.getInstance().getOffscreenBuffer() != null) {
            this.setNightTint(0.0F);
        }

        this.setMinutesStamp();
        int int6 = (int)((this.getTimeOfDay() - (float)((int)this.getTimeOfDay())) * 60.0F);
        if (int6 / 10 != this.minutesMod) {
            IsoPlayer[] isoPlayer4 = IsoPlayer.players;

            for (int int7 = 0; int7 < isoPlayer4.length; int7++) {
                IsoPlayer isoPlayer5 = isoPlayer4[int7];
                if (isoPlayer5 != null) {
                    isoPlayer5.dirtyRecalcGridStackTime = 1.0F;
                }
            }

            ErosionMain.EveryTenMinutes();
            ClimateManager.getInstance().updateEveryTenMins();
            getInstance().updateRoomLight();
            LuaEventManager.triggerEvent("EveryTenMinutes");
            this.minutesMod = int6 / 10;
            ZomboidRadio.getInstance().UpdateScripts(this.getHour(), int6);
        }

        if (this.previousMinuteStamp != this.minutesStamp) {
            LuaEventManager.triggerEvent("EveryOneMinute");
            this.previousMinuteStamp = this.minutesStamp;
        }

        if (GameServer.bServer && (_long - this.lastClockSync > 10000L || GameServer.bFastForward)) {
            GameServer.syncClock();
            this.lastClockSync = _long;
        }
    }

    private void updateRoomLight() {
    }

    private void setMinutesStamp() {
        this.minutesStamp = (long)this.getWorldAgeHours() * 60L + (long)this.getMinutes();
    }

    public long getMinutesStamp() {
        return this.minutesStamp;
    }

    public boolean getThunderStorm() {
        return ClimateManager.getInstance().getIsThunderStorming();
    }

    private void doMetaEvents() {
        byte _byte = 3;
        if (zombie.SandboxOptions.instance.MetaEvent.getValue() == 1) {
            _byte = -1;
        }

        if (zombie.SandboxOptions.instance.MetaEvent.getValue() == 3) {
            _byte = 2;
        }

        this.bGunFireEventToday = _byte != -1 && Rand.Next(_byte) == 0;
        if (this.bGunFireEventToday) {
            this.NumGunFireEvents = 1;

            for (int _int = 0; _int < this.NumGunFireEvents; _int++) {
                this.GunFireTimes[_int] = (float)Rand.Next(18000) / 1000.0F + 7.0F;
            }
        }

        this.randomAmbientToday = true;
    }

    @Deprecated
    public float getAmbient() {
        return ClimateManager.getInstance().getAmbient();
    }

    public void setAmbient(float _Ambient) {
        this.Ambient = _Ambient;
    }

    public float getAmbientMax() {
        return this.AmbientMax;
    }

    public void setAmbientMax(float _AmbientMax) {
        _AmbientMax = Math.min(1.0F, _AmbientMax);
        _AmbientMax = Math.max(0.0F, _AmbientMax);
        this.AmbientMax = _AmbientMax;
    }

    public float getAmbientMin() {
        return this.AmbientMin;
    }

    public void setAmbientMin(float _AmbientMin) {
        _AmbientMin = Math.min(1.0F, _AmbientMin);
        _AmbientMin = Math.max(0.0F, _AmbientMin);
        this.AmbientMin = _AmbientMin;
    }

    public int getDay() {
        return this.Day;
    }

    public int getDayPlusOne() {
        return this.Day + 1;
    }

    public void setDay(int _Day) {
        this.Day = _Day;
    }

    public int getStartDay() {
        return this.StartDay;
    }

    public void setStartDay(int _StartDay) {
        this.StartDay = _StartDay;
    }

    public float getMaxZombieCountStart() {
        return 0.0F;
    }

    public void setMaxZombieCountStart(float _MaxZombieCountStart) {
        this.MaxZombieCountStart = _MaxZombieCountStart;
    }

    public float getMinZombieCountStart() {
        return 0.0F;
    }

    public void setMinZombieCountStart(float _MinZombieCountStart) {
        this.MinZombieCountStart = _MinZombieCountStart;
    }

    public float getMaxZombieCount() {
        return this.MaxZombieCount;
    }

    public void setMaxZombieCount(float _MaxZombieCount) {
        this.MaxZombieCount = _MaxZombieCount;
    }

    public float getMinZombieCount() {
        return this.MinZombieCount;
    }

    public void setMinZombieCount(float _MinZombieCount) {
        this.MinZombieCount = _MinZombieCount;
    }

    public int getMonth() {
        return this.Month;
    }

    public void setMonth(int _Month) {
        this.Month = _Month;
    }

    public int getStartMonth() {
        return this.StartMonth;
    }

    public void setStartMonth(int _StartMonth) {
        this.StartMonth = _StartMonth;
    }

    public float getNightTint() {
        return ClimateManager.getInstance().getNightStrength();
    }

    public void setNightTint(float NightTint) {
    }

    public float getNight() {
        return ClimateManager.getInstance().getNightStrength();
    }

    public void setNight(float NightTint) {
    }

    public float getTimeOfDay() {
        return this.TimeOfDay;
    }

    public void setTimeOfDay(float _TimeOfDay) {
        this.TimeOfDay = _TimeOfDay;
    }

    public float getStartTimeOfDay() {
        return this.StartTimeOfDay;
    }

    public void setStartTimeOfDay(float _StartTimeOfDay) {
        this.StartTimeOfDay = _StartTimeOfDay;
    }

    public float getViewDist() {
        return ClimateManager.getInstance().getViewDistance();
    }

    public float getViewDistMax() {
        return this.ViewDistMax;
    }

    public void setViewDistMax(float _ViewDistMax) {
        this.ViewDistMax = _ViewDistMax;
    }

    public float getViewDistMin() {
        return this.ViewDistMin;
    }

    public void setViewDistMin(float _ViewDistMin) {
        this.ViewDistMin = _ViewDistMin;
    }

    public int getYear() {
        return this.Year;
    }

    public void setYear(int _Year) {
        this.Year = _Year;
    }

    public int getStartYear() {
        return this.StartYear;
    }

    public void setStartYear(int _StartYear) {
        this.StartYear = _StartYear;
    }

    public int getNightsSurvived() {
        return this.NightsSurvived;
    }

    public void setNightsSurvived(int _NightsSurvived) {
        this.NightsSurvived = _NightsSurvived;
    }

    public double getWorldAgeHours() {
        float _float = (float)(this.getNightsSurvived() * 24);
        if (this.getTimeOfDay() >= 7.0F) {
            _float += this.getTimeOfDay() - 7.0F;
        } else {
            _float += this.getTimeOfDay() + 17.0F;
        }

        return (double)_float;
    }

    public double getHoursSurvived() {
        DebugLog.log("GameTime.getHoursSurvived() has no meaning, use IsoPlayer.getHourSurvived() instead");
        return this.HoursSurvived;
    }

    public void setHoursSurvived(double _HoursSurvived) {
        DebugLog.log("GameTime.getHoursSurvived() has no meaning, use IsoPlayer.getHourSurvived() instead");
        this.HoursSurvived = _HoursSurvived;
    }

    public int getHour() {
        double _double = Math.floor((double)(this.getTimeOfDay() * 3600.0F));
        return (int)Math.floor(_double / 3600.0);
    }

    public PZCalendar getCalender() {
        this.updateCalendar(
            this.getYear(), this.getMonth(), this.getDay(), (int)this.getTimeOfDay(), (int)((this.getTimeOfDay() - (float)((int)this.getTimeOfDay())) * 60.0F)
        );
        return this.Calender;
    }

    public void setCalender(PZCalendar _Calender) {
        this.Calender = _Calender;
    }

    public void updateCalendar(int year, int month, int dayOfMonth, int hourOfDay, int minute) {
        if (this.Calender == null) {
            this.Calender = new PZCalendar(new GregorianCalendar());
        }

        this.Calender.set(year, month, dayOfMonth, hourOfDay, minute);
    }

    public float getMinutesPerDay() {
        return this.MinutesPerDay;
    }

    public void setMinutesPerDay(float _MinutesPerDay) {
        this.MinutesPerDay = _MinutesPerDay;
    }

    public float getLastTimeOfDay() {
        return this.LastTimeOfDay;
    }

    public void setLastTimeOfDay(float _LastTimeOfDay) {
        this.LastTimeOfDay = _LastTimeOfDay;
    }

    public void setTargetZombies(int _TargetZombies) {
        this.TargetZombies = _TargetZombies;
    }

    public boolean isRainingToday() {
        return this.RainingToday;
    }

    public float getMultiplier() {
        if (!GameServer.bServer && !GameClient.bClient && IsoPlayer.getInstance() != null && IsoPlayer.allPlayersAsleep()) {
            return 200.0F * (30.0F / (float)PerformanceSettings.getLockFPS());
        } else {
            float _float = 1.0F;
            if (GameServer.bServer && GameServer.bFastForward) {
                _float = (float)ServerOptions.instance.FastForwardMultiplier.getValue() / this.getDeltaMinutesPerDay();
            } else if (GameClient.bClient && GameClient.bFastForward) {
                _float = (float)ServerOptions.instance.FastForwardMultiplier.getValue() / this.getDeltaMinutesPerDay();
            }

            _float *= this.Multiplier;
            _float *= this.FPSMultiplier;
            _float *= this.multiplierBias;
            _float *= this.PerObjectMultiplier;
            if (DebugOptions.instance.GameTimeSpeedQuarter.getValue()) {
                _float *= 0.25F;
            }

            if (DebugOptions.instance.GameTimeSpeedHalf.getValue()) {
                _float *= 0.5F;
            }

            return _float * 0.8F;
        }
    }

    public float getTimeDelta() {
        return this.getMultiplier() / (0.8F * this.multiplierBias) / 60.0F;
    }

    public static float getAnimSpeedFix() {
        return 0.8F;
    }

    public void setMultiplier(float _Multiplier) {
        this.Multiplier = _Multiplier;
    }

    public float getServerMultiplier() {
        float float0 = 10.0F / zombie.GameWindow.averageFPS / (float)(PerformanceSettings.ManualFrameSkips + 1);
        float float1 = this.Multiplier * float0;
        float1 *= 0.5F;
        if (!GameServer.bServer && !GameClient.bClient && IsoPlayer.getInstance() != null && IsoPlayer.allPlayersAsleep()) {
            return 200.0F * (30.0F / (float)PerformanceSettings.getLockFPS());
        } else {
            float1 *= 1.6F;
            return float1 * this.multiplierBias;
        }
    }

    public float getUnmoddedMultiplier() {
        return !GameServer.bServer && !GameClient.bClient && IsoPlayer.getInstance() != null && IsoPlayer.allPlayersAsleep()
            ? 200.0F * (30.0F / (float)PerformanceSettings.getLockFPS())
            : this.Multiplier * this.FPSMultiplier * this.PerObjectMultiplier;
    }

    public float getInvMultiplier() {
        return 1.0F / this.getMultiplier();
    }

    public float getTrueMultiplier() {
        return this.Multiplier * this.PerObjectMultiplier;
    }

    public void save() {
        File file = new File(zombie.ZomboidFileSystem.instance.getFileNameInCurrentSave("map_t.bin"));
        Object object = null;

        try {
            object = new FileOutputStream(file);
        } catch (FileNotFoundException fileNotFoundException) {
            fileNotFoundException.printStackTrace();
            return;
        }

        DataOutputStream dataOutputStream = new DataOutputStream(new BufferedOutputStream((OutputStream)object));

        try {
            instance.save(dataOutputStream);
        } catch (IOException iOException0) {
            iOException0.printStackTrace();
        }

        try {
            dataOutputStream.flush();
            dataOutputStream.close();
        } catch (IOException iOException1) {
            iOException1.printStackTrace();
        }
    }

    public void save(DataOutputStream output) throws IOException {
        output.writeByte(71);
        output.writeByte(77);
        output.writeByte(84);
        output.writeByte(77);
        output.writeInt(195);
        output.writeFloat(this.Multiplier);
        output.writeInt(this.NightsSurvived);
        output.writeInt(this.TargetZombies);
        output.writeFloat(this.LastTimeOfDay);
        output.writeFloat(this.TimeOfDay);
        output.writeInt(this.Day);
        output.writeInt(this.Month);
        output.writeInt(this.Year);
        output.writeFloat(0.0F);
        output.writeFloat(0.0F);
        output.writeInt(0);
        if (this.table != null) {
            output.writeByte(1);
            this.table.save(output);
        } else {
            output.writeByte(0);
        }

        zombie.GameWindow.WriteString(output, Core.getInstance().getPoisonousBerry());
        zombie.GameWindow.WriteString(output, Core.getInstance().getPoisonousMushroom());
        output.writeInt(this.HelicopterDay1);
        output.writeInt(this.HelicopterTime1Start);
        output.writeInt(this.HelicopterTime1End);
        ClimateManager.getInstance().save(output);
    }

    public void save(ByteBuffer output) throws IOException {
        output.putFloat(this.Multiplier);
        output.putInt(this.NightsSurvived);
        output.putInt(this.TargetZombies);
        output.putFloat(this.LastTimeOfDay);
        output.putFloat(this.TimeOfDay);
        output.putInt(this.Day);
        output.putInt(this.Month);
        output.putInt(this.Year);
        output.putFloat(0.0F);
        output.putFloat(0.0F);
        output.putInt(0);
        if (this.table != null) {
            output.put((byte)1);
            this.table.save(output);
        } else {
            output.put((byte)0);
        }
    }

    public void load(DataInputStream input) throws IOException {
        int int0 = IsoWorld.SavedWorldVersion;
        if (int0 == -1) {
            int0 = 195;
        }

        input.mark(0);
        byte byte0 = input.readByte();
        byte byte1 = input.readByte();
        byte byte2 = input.readByte();
        byte byte3 = input.readByte();
        if (byte0 == 71 && byte1 == 77 && byte2 == 84 && byte3 == 77) {
            int0 = input.readInt();
        } else {
            input.reset();
        }

        this.Multiplier = input.readFloat();
        this.NightsSurvived = input.readInt();
        this.TargetZombies = input.readInt();
        this.LastTimeOfDay = input.readFloat();
        this.TimeOfDay = input.readFloat();
        this.Day = input.readInt();
        this.Month = input.readInt();
        this.Year = input.readInt();
        input.readFloat();
        input.readFloat();
        int int1 = input.readInt();
        if (input.readByte() == 1) {
            if (this.table == null) {
                this.table = LuaManager.platform.newTable();
            }

            this.table.load(input, int0);
        }

        if (int0 >= 74) {
            Core.getInstance().setPoisonousBerry(zombie.GameWindow.ReadString(input));
            Core.getInstance().setPoisonousMushroom(zombie.GameWindow.ReadString(input));
        }

        if (int0 >= 90) {
            this.HelicopterDay1 = input.readInt();
            this.HelicopterTime1Start = input.readInt();
            this.HelicopterTime1End = input.readInt();
        }

        if (int0 >= 135) {
            ClimateManager.getInstance().load(input, int0);
        }

        this.setMinutesStamp();
    }

    public void load(ByteBuffer input) throws IOException {
        short _short = 195;
        this.Multiplier = input.getFloat();
        this.NightsSurvived = input.getInt();
        this.TargetZombies = input.getInt();
        this.LastTimeOfDay = input.getFloat();
        this.TimeOfDay = input.getFloat();
        this.Day = input.getInt();
        this.Month = input.getInt();
        this.Year = input.getInt();
        input.getFloat();
        input.getFloat();
        int _int = input.getInt();
        if (input.get() == 1) {
            if (this.table == null) {
                this.table = LuaManager.platform.newTable();
            }

            this.table.load(input, _short);
        }

        this.setMinutesStamp();
    }

    public void load() {
        File file = zombie.ZomboidFileSystem.instance.getFileInCurrentSave("map_t.bin");

        try {
            FileInputStream fileInputStream = new FileInputStream(file);

            try {
                BufferedInputStream bufferedInputStream = new BufferedInputStream(fileInputStream);

                try {
                    synchronized (SliceY.SliceBufferLock) {
                        SliceY.SliceBuffer.clear();
                        int _int = bufferedInputStream.read(SliceY.SliceBuffer.array());
                        SliceY.SliceBuffer.limit(_int);
                        DataInputStream dataInputStream = new DataInputStream(new ByteArrayInputStream(SliceY.SliceBuffer.array(), 0, _int));
                        this.load(dataInputStream);
                    }
                } catch (Throwable throwable0) {
                    try {
                        bufferedInputStream.close();
                    } catch (Throwable throwable1) {
                        throwable0.addSuppressed(throwable1);
                    }

                    throw throwable0;
                }

                bufferedInputStream.close();
            } catch (Throwable throwable2) {
                try {
                    fileInputStream.close();
                } catch (Throwable throwable3) {
                    throwable2.addSuppressed(throwable3);
                }

                throw throwable2;
            }

            fileInputStream.close();
        } catch (FileNotFoundException fileNotFoundException) {
        } catch (Exception exception) {
            ExceptionLogger.logException(exception);
        }
    }

    public int getDawn() {
        return this.dawn;
    }

    public void setDawn(int _dawn) {
        this.dawn = _dawn;
    }

    public int getDusk() {
        return this.dusk;
    }

    public void setDusk(int _dusk) {
        this.dusk = _dusk;
    }

    public KahluaTable getModData() {
        if (this.table == null) {
            this.table = LuaManager.platform.newTable();
        }

        return this.table;
    }

    public boolean isThunderDay() {
        return this.thunderDay;
    }

    public void setThunderDay(boolean _thunderDay) {
        this.thunderDay = _thunderDay;
    }

    public void saveToPacket(ByteBuffer bb) throws IOException {
        KahluaTable kahluaTable = getInstance().getModData();
        Object object0 = kahluaTable.rawget("camping");
        Object object1 = kahluaTable.rawget("farming");
        Object object2 = kahluaTable.rawget("trapping");
        kahluaTable.rawset("camping", null);
        kahluaTable.rawset("farming", null);
        kahluaTable.rawset("trapping", null);
        this.save(bb);
        kahluaTable.rawset("camping", object0);
        kahluaTable.rawset("farming", object1);
        kahluaTable.rawset("trapping", object2);
    }

    public int getHelicopterDay1() {
        return this.HelicopterDay1;
    }

    public int getHelicopterDay() {
        return this.HelicopterDay1;
    }

    public void setHelicopterDay(int day) {
        this.HelicopterDay1 = PZMath.max(day, 0);
    }

    public int getHelicopterStartHour() {
        return this.HelicopterTime1Start;
    }

    public void setHelicopterStartHour(int hour) {
        this.HelicopterTime1Start = PZMath.clamp(hour, 0, 24);
    }

    public int getHelicopterEndHour() {
        return this.HelicopterTime1End;
    }

    public void setHelicopterEndHour(int hour) {
        this.HelicopterTime1End = PZMath.clamp(hour, 0, 24);
    }

    public static boolean isGamePaused() {
        if (GameServer.bServer) {
            return GameServer.Players.isEmpty() && ServerOptions.instance.PauseEmpty.getValue();
        } else if (GameClient.bClient) {
            return GameClient.IsClientPaused();
        } else {
            SpeedControls speedControls = UIManager.getSpeedControls();
            return speedControls != null && speedControls.getCurrentGameSpeed() == 0;
        }
    }

    public static class AnimTimer {
        public float Elapsed;
        public float Duration;
        public boolean Finished = true;
        public int Ticks;

        public void init(int ticks) {
            this.Ticks = ticks;
            this.Elapsed = 0.0F;
            this.Duration = (float)(ticks * 1) / 30.0F;
            this.Finished = false;
        }

        public void update() {
            this.Elapsed = this.Elapsed + zombie.GameTime.instance.getMultipliedSecondsSinceLastUpdate() * 60.0F / 30.0F;
            if (this.Elapsed >= this.Duration) {
                this.Elapsed = this.Duration;
                this.Finished = true;
            }
        }

        public float ratio() {
            return this.Elapsed / this.Duration;
        }

        public boolean finished() {
            return this.Finished;
        }
    }
}
